package com.alg.local.gateway.filter;

import cn.hutool.json.JSONUtil;
import com.alg.local.gateway.entity.SwaggerDocs;
import com.alg.local.gateway.entity.SwaggerServer;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author al
 * @date 2022/1/21 15:24
 * @description 修改swagger-api path
 */
//@Component
@Slf4j
public class SwaggerPathFilter implements GlobalFilter, Ordered {

    private final PathMatcher pathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.debug("只匹配/<service-id>/v3/api-docs路径");
        ServerHttpRequest request = exchange.getRequest();
        String requestUrl = request.getPath().toString();
        boolean match = pathMatcher.match("/**/v3/api-docs", requestUrl);

        if (match) {

            String serviceId = requestUrl.substring(0, requestUrl.indexOf("v3") - 1);
            log.info("当前服务ID：{}", serviceId);

            ServerHttpResponse originalResponse = exchange.getResponse();
            DataBufferFactory bufferFactory = originalResponse.bufferFactory();
            ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                    if (body instanceof Flux) {
                        Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                        return super.writeWith(fluxBody.buffer().map(dataBuffer -> {

                            DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                            DataBuffer join = dataBufferFactory.join(dataBuffer);

                            byte[] content = new byte[join.readableByteCount()];
                            join.read(content);
                            //释放掉内存
                            DataBufferUtils.release(join);
                            // 正常返回的数据
                            String rootData = new String(content, StandardCharsets.UTF_8);

                            // 对数据进行转换 & path拼接
                            SwaggerDocs swaggerDocs = JSONUtil.toBean(rootData, SwaggerDocs.class);
                            List<SwaggerServer> servers = swaggerDocs.getServers();
                            servers.forEach(data -> data.setUrl(data.getUrl() + serviceId));
                            String result = JSONUtil.toJsonStr(swaggerDocs);
                            // 加密后的数据返回给客户端
                            byte[] uppedContent = result.getBytes();
                            return bufferFactory.wrap(uppedContent);
                        }));
                    }
                    return super.writeWith(body);
                }
            };
            return chain.filter(exchange.mutate().response(decoratedResponse).build());
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1;
    }
}
